package com.training.schedule_management_system_admin.service;



import com.training.schedule_management_system_admin.entity.User;
import com.training.schedule_management_system_admin.entity.UserExample;
import com.training.schedule_management_system_admin.mapper.UserMapper;
import com.training.schedule_management_system_admin.utils.MD5Utils;
import com.training.schedule_management_system_admin.utils.UserUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class UserService {

    @Autowired
    UserMapper userMapper;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    /*
     判断当前登录的用户是否被限制登录
     */
    public Map<String,Object> loginUserLock(String username){
        Map<String,Object> map=new HashMap<>();
        String key= UserUtils.getLoginTimeLockKey(username);
        if(stringRedisTemplate.hasKey(key)){//如果存在，说明被限制登录
            Long lockTime = stringRedisTemplate.getExpire(key, TimeUnit.MINUTES);//获得该用户的剩余限制时间，以分钟形式返回
            map.put("flag",true);
            map.put("lockTime",lockTime);
        }else{//不存在，说明没有被限制登录
            map.put("flag",false);
        }
        return map;
    }

    /*
    密码输入错误相应操作
     */
    public String loginValdate(String username){
        int num=5;//允许密码错误的次数
        int minute=5;//失效期
        String key = UserUtils.getLoginFailCountKey(username);
        if(!stringRedisTemplate.hasKey(key)){//如果不存在，则是第一次密码错误
            //设置第一次密码错误次数为1，并设置失效期5分钟
            stringRedisTemplate.opsForValue().set(key,"1");
            stringRedisTemplate.expire(key,minute,TimeUnit.MINUTES);
            return "密码错误，在"+minute+"分钟内还允许输入错误"+(num-1)+"次";
        }else{//如果存在，则是第二次以上面膜错误
            //先查询该用户密码次数
            long loginFailCount = Long.parseLong(stringRedisTemplate.opsForValue().get(key));
            if(loginFailCount<(num-1)){//如果当前密码错误次数<num-1,则表示还能继续尝试
                stringRedisTemplate.opsForValue().increment(key,1);//密码错误次数+1
                Long seconds = stringRedisTemplate.getExpire(key, TimeUnit.SECONDS);
                return "密码错误,在"+seconds+"秒内还允许输入错误"+(num-1-loginFailCount)+"次";
            }else{//如果超过允许密码错误的次数
                int hour=1;
                //将该用户限制登录，同时设置限制时间1小时
                stringRedisTemplate.opsForValue().set(UserUtils.getLoginTimeLockKey(username),"1");
                stringRedisTemplate.expire(UserUtils.getLoginTimeLockKey(username),hour,TimeUnit.HOURS);
                return "因为密码错误次数超过限制"+num+"次,已对该用户限制登录1小时";
            }
        }
    }

    /*
    设置验证码
     */
    public void setCode(String email,String code){
        String key=email+"验证码:";
        stringRedisTemplate.opsForValue().set(key,code);
        stringRedisTemplate.expire(key,5,TimeUnit.MINUTES);
    }

    //验证验证码是否一致
    public boolean checkCode(String email,String code){
        String key=email+"验证码:";
        String value = stringRedisTemplate.opsForValue().get(key);
        return code.equals(value);
    }

    /*
    判断用户名是否已存在
     */
    public boolean checkUserByUsername(String username) {
        UserExample example=new UserExample();
        UserExample.Criteria criteria = example.createCriteria();
        criteria.andUsernameEqualTo(username);
        Long counts=userMapper.countByExample(example);
        return counts==0;
    }

    /*
    根据用户名和密码得到用户
     */
    public User getUser(String username, String password) {
        return userMapper.getUser(username, MD5Utils.code(password));
    }

    /*
    根据用户名得到用户
     */
    public User getUserByUsername(String username){
        return userMapper.getUserByUsername(username);
    }

    /*
    根据邮箱得到用户
     */
    public User getUserByEmail(String email){
        UserExample example=new UserExample();
        UserExample.Criteria criteria = example.createCriteria();
        criteria.andEmailEqualTo(email);
        List<User> users = userMapper.selectByExample(example);
        if(users!=null && !users.isEmpty()){
            return users.get(0);
        }else{
            return null;
        }
    }

    /*
    判断邮箱是否已被注册
     */
    public boolean checkUserByEmail(String email) {
        UserExample example=new UserExample();
        UserExample.Criteria criteria = example.createCriteria();
        criteria.andEmailEqualTo(email);
        Long counts=userMapper.countByExample(example);
        return counts==0;
    }

    /*
    保存用户
     */
    @Transactional
    public int saveUser(User user) {
        user.setPassword(MD5Utils.code(user.getPassword()));
        String result = stringRedisTemplate.opsForValue().get("是否开放注册");
        boolean flag=Boolean.parseBoolean(result);
        if(flag){//开放注册
            user.setAuditState(1);
        }else{//关闭开放注册
            user.setAuditState(0);
        }
        return userMapper.insertSelective(user);
    }

    /*
    根据用户id得到用户以及对应的角色和权限
     */
    public User getUserWithRole(Integer id) {
        return userMapper.getUserWithRoleById(id);
    }


    /*
    为新注册的用户设置角色和权限
     */
    public int saveRole(Integer userId, Integer roleId) {
        return userMapper.insertUserAndRole(userId,roleId);
    }

    /*
    获取所有的用户
     */
    public List<User> getAll() {
        UserExample example=new UserExample();
        example.setOrderByClause("audit_state asc");
        return userMapper.selectByExample(example);
    }

    /*
    审核用户
     */
    @Transactional
    public void auditUser(User user) {
        user.setAuditState(1);
        userMapper.updateByPrimaryKeySelective(user);
    }

    /*
    修改密码
     */
    public int reset(User user) {
        return userMapper.updateByPrimaryKeySelective(user);
    }
}
